import track, { pauseTracking, resumeTracking } from "../../effect/track.js";
import { reactive } from "../../reactive.js";
import { TrackOpTypes, isObject, RAW } from "../../utils.js";

const arrayInstrumentations = {};
// 重写数组的 includes、indexOf、lastIndexOf 方法
["includes", "indexOf", "lastIndexOf"].forEach((key) => {
  arrayInstrumentations[key] = function (...args) {
    // 先正常查找，this 指向代理对象
    const res = Array.prototype[key].apply(this, args);
    if (res < 0 || res === false) {
      // 找不到时，返回原始对象
      return Array.prototype[key].apply(this[RAW], args);
    }
    return res;
  };
});
// 重写 push、pop、shift、unshift
// 在调用这几个方法的时候，需要暂停依赖收集，调用完毕之后再恢复
["push", "pop", "shift", "unshift", "splice"].forEach((key) => {
  arrayInstrumentations[key] = function (...args) {
    pauseTracking(); // 暂停收集依赖
    const res = Array.prototype[key].apply(this, args);
    resumeTracking(); // 恢复收集依赖
    return res;
  };
});

/**
 * 拦截 get 操作
 * @param {*} target
 * @param {*} key
 * @returns
 */
export default function (target, key) {
  if (key === RAW) {
    return target;
  }

  // 进行依赖收集
  track(target, TrackOpTypes.GET, key);

  // 重写数组的一些方法
  if (arrayInstrumentations.hasOwnProperty(key) && Array.isArray(target)) {
    return arrayInstrumentations[key];
  }

  const result = Reflect.get(target, key);

  // 若为对象，递归处理为响应式
  if (isObject(result)) {
    return reactive(result);
  }
  return result;
}
